package proxy.dynamic;

import java.lang.reflect.Proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * 代理模式:Proxy Pattern Java对代理模式的支持:
 * java.lang.reflect.Proxy、java.lang.reflect.InvocationHandler.
 * 
 * @version 2009-6-27
 * @author Winty(wintys@gmail.com)
 */
public class DynamicProxyTest {
	public static void main(String[] args) {
		Subject subject = new RealSubject();
		Subject proxy = (Subject) DynamicProxySubjectFactory.factory(subject);
		proxy.request();
	}
}

/**
 * 抽象主题角色
 */
abstract interface Subject {
	public void request();
}

/**
 * 真实主题角色
 */
class RealSubject implements Subject {
	@Override
	public void request() {
		System.out.println("do request.");
	}
}

class DynamicProxyHandler implements InvocationHandler {
	private Subject realSubject;

	public DynamicProxyHandler(Subject realSubject) {
		this.realSubject = realSubject;
	}

	// proxy代表Proxy生成的代理对象实例$Proxy0
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

		preRequest();
		Object result = method.invoke(realSubject, args);
		postRequest();

		return result;
	}

	private void preRequest() {
		System.out.println("do preRequest");
	}

	private void postRequest() {
		System.out.println("do postRequest");
	}
}

/**
 * 动态代理类工厂 : 由Poxy类动态生成一个代理类(如:$Proxy0)。
 */
class DynamicProxySubjectFactory {
	/**
	 * @param subject
	 *            被代理的真实对象。Subject必须为接口， 即subject的真实类型是实现了Subject接口的类。
	 *            因为JDK的动态代理并不能随心所欲的代理所有的，
	 *            Proxy.newProxyInstance()的第二个参数决定只能代理接口。
	 * 
	 * @return 代理类实例
	 */
	public static Object factory(Subject subject) {
		Class<?> cls = subject.getClass();
		DynamicProxyHandler handler = new DynamicProxyHandler(subject);

		return Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), handler);
	}
}
